// 文件名：unordered_map_string_intern.cpp
// 目的：实现字符串驻留（intern）：对于相同内容的字符串，仅存储一份并返回稳定的 string_view。
// 设计：
//   - table_：unordered_map<string, int>，键保存唯一的字符串副本，值无关（此处占位 int）；
//   - intern(s)：若已存在则直接返回已存 key 的 string_view；否则插入新键并返回其视图；
//   - 使用透明哈希与比较（可异构查找 string_view 与 string，避免临时分配）。
// 特性与注意：
//   - 返回的 string_view 指向 map 中 key 的内部存储，稳定性与其生命周期绑定；
//   - 别在 map 擦除前持久化或跨线程使用该视图；
//   - 示例中比较 &a == &c 比较的是本地变量 string_view 对象地址，无意义；应比较 a.data()==c.data()。
// 复杂度：intern 均摊 O(1)。

#include <iostream>
#include <string>
#include <string_view>
#include <unordered_map>

class StringPool {
public:
    // 将字符串驻留：返回指向池内存储的 string_view
    std::string_view intern(const std::string& s) {
        if (auto it = table_.find(s); it != table_.end()) {
            return it->first; // 已存在：返回已存 key 的视图
        }
        auto [it, inserted] = table_.emplace(std::make_pair(s, 0)); // 插入新 key
        return it->first; // 返回新存储的视图
    }

    std::size_t size() const noexcept { return table_.size(); }

private:
    // 透明哈希：支持 string / string_view 异构查找
    struct TransparentHash {
        using is_transparent = void;
        std::size_t operator()(std::string_view sv) const noexcept {
            return std::hash<std::string_view>{}(sv);
        }
    };
    // 透明相等：支持 string / string_view 比较
    struct TransparentEqual {
        using is_transparent = void;
        bool operator()(std::string_view lhs, std::string_view rhs) const noexcept {
            return lhs == rhs;
        }
    };

    std::unordered_map<std::string, int, TransparentHash, TransparentEqual> table_;
};

int main() {
    StringPool pool;
    auto a = pool.intern("hello");
    auto b = pool.intern("world");
    auto c = pool.intern("hello"); // 返回同一驻留条目

    std::cout << "Pool size: " << pool.size() << '\n';
    std::cout << "a ptr == c ptr? " << std::boolalpha << (&a == &c) << '\n'; // 比较局部对象地址，无意义
    std::cout << "a data address == c data address? "
              << (a.data() == c.data()) << '\n'; // 应该比较底层数据地址

    return 0;
}